package com.wdm.diffutils.util;

import com.wdm.diffutils.marker.Aggregate;
import com.wdm.diffutils.marker.Identifier;

import java.lang.reflect.Field;

/**
 * Description:
 *
 * @author wudaiming
 * @date 2023/10/26 12:38
 */
public class ReflectionUtils {
    
    /**
     * Sets the value of the specified field in the given aggregate to the provided value.
     * The field is identified by its name. This method is intended to be used with objects
     * that implement the Aggregate interface.
     *
     * @param fieldName the name of the field to set
     * @param aggregate the aggregate object whose field should be set
     * @param value     the value to set the field to
     * @param <T>       the type of the aggregate
     * @param <ID>      the type of the identifier
     * @throws IllegalArgumentException if the field does not exist, cannot be accessed, or if inputs are invalid.
     */
    public static <T extends Aggregate<ID>, ID extends Identifier<?>> void writeField(String fieldName, T aggregate, ID value) {
        
        if (fieldName == null || fieldName.isEmpty()) {
            throw new IllegalArgumentException("Field name cannot be null or empty");
        }
        if (aggregate == null) {
            throw new IllegalArgumentException("Aggregate cannot be null");
        }
        
        try {
            Field field = aggregate.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(aggregate, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new IllegalArgumentException("Error writing to field: " + fieldName, e);
        }
    }
    
}
